﻿using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web.Mvc;
using CID.Domain.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using CID.Web.Support.TemplateContentEdition;

namespace CID.Web.Models.Infrastructure
{
    public class TemplateViewModel : BaseDescribedViewModel<ITemplate>, IAjaxEnabledViewModel
    {
        #region Properties
        public bool Enabled { get; set; }
        public string Content { get; set; }

        [HiddenInput(DisplayValue = false)]
        [Required(ErrorMessage = "You must provide a Template Type")]
        public int? TemplateTypeId { get; set; }
        [Display(Name = "Template Type")]
        public string TemplateType { get; set; }
        [Display(Name = "Support For Multiple Servers")]
        public bool MultipleServersSupport { get; set; }
        
        [Required(ErrorMessage = "You must select a Purpose")]
        [JsonConverter(typeof(StringEnumConverter))]
        public TemplatePurpose Purpose { get; set; }

        public List<ParameterViewModel> Parameters { get; set; }

        public string PostUrl { get; set; }
        #endregion

        public TemplateViewModel() : base() 
        {
            Parameters = new List<ParameterViewModel>();
        }

        public TemplateViewModel(ITemplate model) : base(model)
        {
            Parameters = new List<ParameterViewModel>();

            Enabled = model.Enabled;
            MultipleServersSupport = model.MultipleServersSupport;
            if (model.Type != null)
            {
                TemplateTypeId = model.Type.Id;
                TemplateType = model.Type.Name;
                ContentEditor = TemplateContentEditorRegistry.Instance.GetEditor(model.Type);
                Content = ContentEditor.Converter.ToString(model.Content);
            }

            if (model is IActivationTemplate) Purpose = TemplatePurpose.Activation;
            else if (model is IDeactivationTemplate) Purpose = TemplatePurpose.Deactivation;
            else if (model is IDeploymentTemplate) Purpose = TemplatePurpose.Deployment;

            foreach (var parameter in model.Parameters)
                Parameters.Add(new ParameterViewModel(parameter));
        }

        public override void UpdateModel(ITemplate model)
        {
            base.UpdateModel(model);
            model.Enabled = Enabled;
            model.MultipleServersSupport = MultipleServersSupport;
            model.Content = ContentEditor.Converter.ToBinaryContent(Content);
            
            foreach (var modifiedParameter in ModifiedParameters)
            {
                var parameter = model.Parameters.SingleOrDefault(x => x.Id == modifiedParameter.Id);
                modifiedParameter.UpdateModel(parameter);
            }

            foreach (var removedParameter in RemovedParameters)
            {
                var parameter = model.Parameters.SingleOrDefault(x => x.Id == removedParameter.Id);
                model.RemoveParameter(parameter);
            }

            foreach (var insertedParameter in InsertedParameters)
            {
                var parameter = model.CreateParameter(insertedParameter.Name, insertedParameter.Description, insertedParameter.Type);
                insertedParameter.UpdateModel(parameter);
            }
        }

        private IEnumerable<ParameterViewModel> InsertedParameters 
        {
            get { return Parameters.Where(x => ((x.Id == 0) && !x._destroy)); }
        }

        private IEnumerable<ParameterViewModel> RemovedParameters
        {
            get { return Parameters.Where(x => ((x.Id != 0) && x._destroy)); }
        }

        private IEnumerable<ParameterViewModel> ModifiedParameters
        {
            get { return Parameters.Where(x => ((x.Id != 0) && !x._destroy)); }
        }

        #region Edition helper members
        #region TemplateTypes
        private IEnumerable<TemplateType> availableTemplateTypes;

        public void SetAvailableTemplateTypes(IEnumerable<TemplateType> availableTemplateTypes)
        {
            this.availableTemplateTypes = availableTemplateTypes;
        }

        [JsonIgnore]
        public IEnumerable<TemplateTypeViewModel> AvailableTemplateTypes
        {
            get { return availableTemplateTypes.ToList().Select(x => new TemplateTypeViewModel(x)); }
        }
        #endregion

        [JsonIgnore]
        public TemplateContentEditor ContentEditor { get; set; }
        #endregion
    }
}